/**
  ******************************************************************************
  * @file    sym32l010_hal_adc.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   ADC HAL module driver.
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "sym32l010_hal_adc.h"


/*******************************************************************************
  * @brief  ADC 初始化
  * @param  InitStruct: 初始化结构体
  * @retval None
  * @note   需通过APBENx寄存器使能ADC的时钟后，才可调用该函数
  */
void HAL_ADC_Init(ADC_InitTypeDef *InitStruct)
{
    SYM_ADC->CR = (uint32_t)InitStruct->ClockSource | (uint32_t)InitStruct->WorkMode |
                  (uint32_t)InitStruct->BgrEn       | (uint32_t)InitStruct->TempSensorEn;
}


/*******************************************************************************
  * @brief  ADC 反初始化
  * @param  None
  * @retval None
  */
void HAL_ADC_DeInit(void)
{
    REGBITS_CLR(SYM_SYSCTRL->APBRST1, SYSCTRL_APBRST1_ADC_Msk);
    REGBITS_SET(SYM_SYSCTRL->APBRST1, SYSCTRL_APBRST1_ADC_Msk);
}


/*******************************************************************************
  * @brief  使能或禁止内置温度传感器
  * @param  TempSensorEn: 内置温度传感器配置
  *                       @arg ADC_TS_ENABLE
  *                       @arg ADC_TS_DISABLE
  * @retval None
  */
void HAL_ADC_TempSensor_Config(ADC_TempSensorEnTypeDef TempSensorEn)
{
    REGBITS_MODIFY(SYM_ADC->CR, ADC_CR_TSEN_Msk, (uint32_t)TempSensorEn);
}


/*******************************************************************************
  * @brief  使能或禁止内置基准电压源
  * @param  BgrEn: 内置基准电压源配置
  *                @arg ADC_BGR_ENABLE
  *                @arg ADC_BGR_DISABLE
  * @retval None
  */
void HAL_ADC_BGR_Config(ADC_BgrEnTypeDef BgrEn)
{
    REGBITS_MODIFY(SYM_ADC->CR, ADC_CR_BGREN_Msk, (uint32_t)BgrEn);
}


/*******************************************************************************
  * @brief  配置ADC工作时钟来源
  * @param  ClockSource: 工作时钟来源
  *                      @arg ADC_CLKSRC_DIV1
  *                      @arg ADC_CLKSRC_DIV2
  *                      @arg ADC_CLKSRC_DIV4
  *                      @arg ADC_CLKSRC_DIV8
  * @retval None
  * @note   ADC采样转换速率应符合用户手册的要求
  */
void HAL_ADC_ClockSource_Config(ADC_ClockSourceTypeDef ClockSource)
{
    REGBITS_MODIFY(SYM_ADC->CR, ADC_CR_CLKSRC_Msk, (uint32_t)ClockSource);
}


/*******************************************************************************
  * @brief  配置工作模式
  * @param  WorkMode: 工作模式
  *                   @arg ADC_WORKMODE_ONESHOT
  *                   @arg ADC_WORKMODE_CONTINUE
  * @retval None
  */
void HAL_ADC_WorkMode_Config(ADC_WorkModeTypeDef WorkMode)
{
    REGBITS_MODIFY(SYM_ADC->CR, ADC_CR_CONT_Msk, (uint32_t)WorkMode);
}


/*******************************************************************************
  * @brief  使能ADC
  * @param  None
  * @retval None
  */
void HAL_ADC_Enable(void)
{
    REGBITS_SET(SYM_ADC->CR, ADC_CR_EN_Msk);
    FirmwareDelay(SystemCoreClock / 1000000);                         // 等待ADC模块稳定
}


/*******************************************************************************
  * @brief  禁止ADC
  * @param  None
  * @retval None
  */
void HAL_ADC_Disable(void)
{
    REGBITS_CLR(SYM_ADC->CR, ADC_CR_EN_Msk);
}


/*******************************************************************************
  * @brief  配置单个通道的模拟输入源和采样时间
  * @param  SqrChannel: 待配置的序列通道号
  * @param  Input:      单通道采样的模拟输入源
  * @param  SampleTime: 单通道采样的采样时间
  * @retval None
  */
void HAL_ADC_OneSqrChannel_Config(ADC_SqrChannelTypeDef SqrChannel,
                                  ADC_SqrChInputTypeDef Input,
                                  ADC_SqrChSampleTimeTypeDef SampleTime)
{
    uint32_t sqrPosition = ((uint32_t)SqrChannel) * 4;
    REGBITS_MODIFY(SYM_ADC->SQRCFR, 0xFUL << sqrPosition, Input << sqrPosition);
    REGBITS_MODIFY(SYM_ADC->SAMPLE, 0xFUL << sqrPosition, SampleTime << sqrPosition);
}


/*******************************************************************************
  * @brief  配置所有序列通道的模拟输入源和采样时间
  * @param  SqrInitStruct: 序列初始化结构体
  * @retval None
  */
void HAL_ADC_AllSqrChannel_Config(ADC_SqrInitTypeDef *SqrInitStruct)
{
    REGBITS_MODIFY(SYM_ADC->CR, ADC_CR_ENS_Msk, (uint32_t)SqrInitStruct->SqrEns);

    SYM_ADC->SQRCFR = ((uint32_t)SqrInitStruct->SqrCh0In << ADC_SQRCFR_SQRCH0_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh1In << ADC_SQRCFR_SQRCH1_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh2In << ADC_SQRCFR_SQRCH2_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh3In << ADC_SQRCFR_SQRCH3_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh4In << ADC_SQRCFR_SQRCH4_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh5In << ADC_SQRCFR_SQRCH5_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh6In << ADC_SQRCFR_SQRCH6_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh7In << ADC_SQRCFR_SQRCH7_Pos);

    SYM_ADC->SAMPLE = ((uint32_t)SqrInitStruct->SqrCh0Sam << ADC_SAMPLE_SQRCH0_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh1Sam << ADC_SAMPLE_SQRCH1_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh2Sam << ADC_SAMPLE_SQRCH2_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh3Sam << ADC_SAMPLE_SQRCH3_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh4Sam << ADC_SAMPLE_SQRCH4_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh5Sam << ADC_SAMPLE_SQRCH5_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh6Sam << ADC_SAMPLE_SQRCH6_Pos) |
                      ((uint32_t)SqrInitStruct->SqrCh7Sam << ADC_SAMPLE_SQRCH7_Pos);
}


/*******************************************************************************
  * @brief  配置模拟看门狗参数
  * @param  Input: 待监测的输入通道
  *                @arg ADC_AWD_IN0  @arg ADC_AWD_IN1  @arg ADC_AWD_IN2  @arg ADC_AWD_IN3
  *                @arg ADC_AWD_IN4  @arg ADC_AWD_IN5  @arg ADC_AWD_IN6  @arg ADC_AWD_IN7
  *                @arg ADC_AWD_IN8  @arg ADC_AWD_IN9  @arg ADC_AWD_IN10 @arg ADC_AWD_IN11
  *                @arg ADC_AWD_IN12 @arg ADC_AWD_IN13 @arg ADC_AWD_TS   @arg ADC_AWD_Bgr1V2
  *                @arg ADC_AWD_All
  * @param  ThresholdHigh: 模拟看门狗检测高阈值
  *                        0x000 - 0xFFF
  * @param  ThresholdLow : 模拟看门狗检测低阈值
  *                        0x000 - 0xFFF
  * @retval None
  */
void HAL_ADC_AWD_Config(uint32_t AwdInSel, uint16_t ThresholdHigh, uint16_t ThresholdLow)
{
    SYM_ADC->AWDTR = (ThresholdHigh << 16) | ThresholdLow;
    SYM_ADC->AWDCR = AwdInSel;
}


/*******************************************************************************
  * @brief  配置硬件触发功能
  * @param  TrigSource: ADC的触发源
  *                    @arg ADC_TRS_None       @arg ADC_TRS_ATIM_TRGO  @arg ADC_TRS_ATIM_TRGO2
  *                    @arg ADC_TRS_ATIM_CC1   @arg ADC_TRS_ATIM_CC2   @arg ADC_TRS_ATIM_CC3
  *                    @arg ADC_TRS_ATIM_CC4   @arg ADC_TRS_ATIM_CC5   @arg ADC_TRS_ATIM_CC6
  *                    @arg ADC_TRS_GTIM1_TRGO @arg ADC_TRS_GTIM1_CC1  @arg ADC_TRS_GTIM1_CC2
  *                    @arg ADC_TRS_GTIM1_CC3  @arg ADC_TRS_GTIM1_CC4  @arg ADC_TRS_BTIM1_TRGO
  *                    @arg ADC_TRS_BTIM2_TRGO @arg ADC_TRS_BTIM3_TRGO @arg ADC_TRS_SPI1
  *                    @arg ADC_TRS_UART1      @arg ADC_TRS_UART2
  * @retval None
  * @note   触发完成后，需要清除产生触发的中断标志
  */
void HAL_ADC_Trigger_Config(uint32_t TriggerSource)
{
    SYM_ADC->TRIGGER = (uint32_t)TriggerSource;
}


/*******************************************************************************
  * @brief  启动ADC转换
  * @param  None
  * @retval None
  */
void HAL_ADC_Start(void)
{
    SYM_ADC->START = 0x01;
}


/*******************************************************************************
  * @brief  停止ADC持续转换模式
  * @param  None
  * @retval None
  * @note   适用于序列持续转换模式
  */
void HAL_ADC_Stop(void)
{
    SYM_ADC->START = 0x00;
}


/*******************************************************************************
  * @brief  等待ADC转换完成
  * @param  None
  * @retval None
  * @note   不适用于持续转换模式
  */
void HAL_ADC_WaitComplete(void)
{
    while (SYM_ADC->START) { ; }
}


/*******************************************************************************
  * @brief  读取ADC转换结果
  * @param  None
  * @retval ADC转换结果
  * @note   None
  */
uint16_t HAL_ADC_Result0_Read(void)                                   // SQR0转换结果或单通道模式转换结果
{
    return SYM_ADC->SQRRESULT0;
}

uint16_t HAL_ADC_Result1_Read(void)                                   // SQR1转换结果
{
    return SYM_ADC->SQRRESULT1;
}

uint16_t HAL_ADC_Result2_Read(void)                                   // SQR2转换结果
{
    return SYM_ADC->SQRRESULT2;
}

uint16_t HAL_ADC_Result3_Read(void)                                   // SQR3转换结果
{
    return SYM_ADC->SQRRESULT3;
}

uint16_t HAL_ADC_Result4_Read(void)                                   // SQR4转换结果
{
    return SYM_ADC->SQRRESULT4;
}

uint16_t HAL_ADC_Result5_Read(void)                                   // SQR5转换结果
{
    return SYM_ADC->SQRRESULT5;
}

uint16_t HAL_ADC_Result6_Read(void)                                   // SQR6转换结果
{
    return SYM_ADC->SQRRESULT6;
}

uint16_t HAL_ADC_Result7_Read(void)                                   // SQR7转换结果
{
    return SYM_ADC->SQRRESULT7;
}


/*******************************************************************************
  * @brief  将 BgrCode 转换为 Avcc 电压
  * @param  BgrCode: ADC转换 BGR1V2 通道的结果
  * @retval Avcc电压, 以V为单位
  * @note   None
  */
float HAL_ADC_BgrResult2Avcc(uint16_t BgrCode)
{
    float Avcc = ADC_Bgr1V2_Voltage * 4.095f / BgrCode;
    return Avcc;
}


/*******************************************************************************
  * @brief  将 TsCode 转换为温度
  * @param  TsCode: ADC转换 TS 通道的结果
  * @param  Avcc:   基准电压, 以V为单位
  * @retval TS的温度值
  * @note   None
  */
float HAL_ADC_TsResult2Tempreture(uint16_t TsCode, float Avcc)
{
    float Vcur = Avcc * TsCode / 4.095f;
    float tmp  = Vcur < ADC_Ts_Voltage ? 0.3841 : 0.4021;
    float Trec = ADC_Ts_TA * 0.5f;
    float Temp = Trec + tmp * (Vcur - ADC_Ts_Voltage);
    return Temp;
}


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
